package com.example.springbootdemo.controller;

import com.example.springbootdemo.utils.EncryptUtil;
import lombok.extern.slf4j.Slf4j;
import net.glxn.qrgen.core.image.ImageType;
import net.glxn.qrgen.javase.QRCode;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URI;
import java.net.URLEncoder;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

@RestController
@RequestMapping("/resource")
@Slf4j
public class ResourceController {

    /**
     * 多文件打包成zip返回流
     * <a href="https://blog.csdn.net/sgl520lxl/article/details/99844263">...</a>
     */
    @GetMapping("/zip/download")
    public void downloadKey(HttpServletResponse response) throws IOException {
        //这里设置打包后的zip文件名
        String downloadName = "qrcode.zip";
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(downloadName, "UTF-8"));
        OutputStream outputStream = response.getOutputStream();
        ZipArchiveOutputStream zous = new ZipArchiveOutputStream(outputStream);
        zous.setUseZip64(Zip64Mode.AsNeeded);
        zous.setEncoding("utf-8");
        try {
            for (int i = 0; i < 10; i++) {
                String url = "https://blog.csdn.net/sgl520lxl/article/details/99844263";
                //打包文件里的每个文件的名字
                String imgName = "qrcode" + i + ".png";
                ByteArrayOutputStream out = QRCode.from(url).to(ImageType.PNG).withSize(300, 300).stream();
                byte[] bytes = out.toByteArray();
                ArchiveEntry entry = new ZipArchiveEntry(imgName);
                zous.putArchiveEntry(entry);
                zous.write(bytes);
                zous.closeArchiveEntry();
            }
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("---------------生成二维码打包流出错----------------" + e.getMessage());
        } finally {
            // 这里要先关zous再关outputStream。否则下载的文件不能正常解压
            zous.close();
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }

    /**
     * 生成RSA密钥对，导出到pem文件，打包成zip后返回流
     */
    @GetMapping("/rsa/zip/download")
    public void downloadRsaPemZip(HttpServletResponse response) {
        //这里设置打包后的zip文件名
        String downloadName = "_RSA密钥" + ".zip";
        OutputStream outputStream = null;
        ZipArchiveOutputStream zous = null;
        try {
            KeyPair keyPair = EncryptUtil.RSA.genKeyPair();
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            String publicKey = Base64.encodeBase64String(rsaPublicKey.getEncoded());
            String privateKey = Base64.encodeBase64String(rsaPrivateKey.getEncoded());

            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(downloadName, "UTF-8"));
            outputStream = response.getOutputStream();
            zous = new ZipArchiveOutputStream(outputStream);
            zous.setUseZip64(Zip64Mode.AsNeeded);
            zous.setEncoding("utf-8");
            ArchiveEntry pubEntry = new ZipArchiveEntry("platform_public_key.pem");
            zous.putArchiveEntry(pubEntry);
            zous.write(getKeyBytes("PUBLIC KEY", publicKey));
            zous.closeArchiveEntry();
            ArchiveEntry priEntry = new ZipArchiveEntry("merchant_private_key.pem");
            zous.putArchiveEntry(priEntry);
            zous.write(getKeyBytes("PRIVATE KEY", privateKey));
            zous.closeArchiveEntry();
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("下载秘钥错误" + e.getMessage());
        } finally {
            try {
                if (zous != null) {
                    zous.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                log.error("close error!", e);
            }
        }
    }


    public byte[] getKeyBytes(String prefix, String keyContent) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PemWriter pemWriter = new PemWriter(new OutputStreamWriter(out));
        try {
            pemWriter.writeObject(new PemObject(prefix, keyContent.getBytes()));
            pemWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return out.toByteArray();
    }

    public static void main(String[] args) {
        UriComponents uriComponents = UriComponentsBuilder
                .fromUriString("https://example.com/hotels/{hotel}")
                .queryParam("q", "{q}")
                .encode()
                .build();

        URI uri = uriComponents.expand("Westin", "123").toUri();
        System.out.println(uri);
    }


}
